package com.muxue.common.utils.date;

import org.apache.commons.lang3.time.DateFormatUtils;

import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

/**
 * 日期时间工具类（合并优化版）
 * - 基于 Java 8+ 的 java.time API
 * - 兼容旧版 Date 对象
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {

    // ====================== 日期格式常量 ======================
    public static final String FORMAT_YYYY = "yyyy";
    public static final String FORMAT_YYYY_MM = "yyyy-MM";
    public static final String FORMAT_YYYY_MM_DD = "yyyy-MM-dd";
    public static final String FORMAT_YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
    public static final String FORMAT_YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    // 日期类型与格式化逻辑的映射
    private static final Map<Class<?>, Function<Object, String>> FORMATTERS = new HashMap<>();

    static {
        // 注册 Date 类型的格式化逻辑
        FORMATTERS.put(Date.class, val -> DateUtils.format((Date) val, FORMAT_YYYY_MM_DD));

        // 注册 LocalDateTime 类型的格式化逻辑
        FORMATTERS.put(LocalDateTime.class, val -> ((LocalDateTime) val).format(DateTimeFormatter.ofPattern(FORMAT_YYYY_MM_DD)));

        // 注册 LocalDate 类型的格式化逻辑
        FORMATTERS.put(LocalDate.class, val -> ((LocalDate) val).format(DateTimeFormatter.ofPattern(FORMAT_YYYY_MM_DD)));
    }

    // 线程安全的格式化器
    private static final DateTimeFormatter FORMAT_YYYY_MM_DDTER =
            DateTimeFormatter.ofPattern(FORMAT_YYYY_MM_DD_HH_MM_SS);

    // ====================== 新版 API（优先使用 java.time） ======================

    /**
     * 转换 TemporalAccessor 为 Date
     */
    public static Date toDate(TemporalAccessor temporal) {
        if (temporal instanceof LocalDateTime) {
            return Date.from(((LocalDateTime) temporal).atZone(ZoneId.systemDefault()).toInstant());
        } else if (temporal instanceof LocalDate) {
            return Date.from(((LocalDate) temporal).atStartOfDay(ZoneId.systemDefault()).toInstant());
        }
        throw new IllegalArgumentException("Unsupported temporal type: " + temporal.getClass());
    }

    /**
     * 转换 Date 为 LocalDateTime
     */
    public static LocalDateTime toLocalDateTime(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    /**
     * 判断是否过期（基于当前时间）
     */
    public static boolean isExpired(LocalDateTime time) {
        return LocalDateTime.now().isAfter(time);
    }

    /**
     * 计算两个日期的天数差（绝对值）
     */
    public static long daysBetween(Date start, Date end) {
        return Math.abs(end.getTime() - start.getTime()) / TimeUnit.DAYS.toMillis(1);
    }

    /**
     * 格式化时间差（天/小时/分钟）
     */
    public static String formatDuration(Date start, Date end) {
        Duration duration = Duration.between(toLocalDateTime(start), toLocalDateTime(end));
        return String.format("%d天%d小时%d分钟",
                duration.toDays(),
                duration.toHoursPart(),
                duration.toMinutesPart());
    }

    /**
     * 判断是否为今天
     */
    public static boolean isToday(LocalDateTime date) {
        return LocalDate.now().equals(date.toLocalDate());
    }

    /**
     * 判断是否为昨天
     */
    public static boolean isYesterday(LocalDateTime date) {
        return LocalDate.now().minusDays(1).equals(date.toLocalDate());
    }
    /**
     * 获取服务器启动时间
     */
    public static Date getServerStartDate()
    {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }

    /**
     * 格式化不同类型的日期对象
     *
     * @param dateFormat 日期格式
     * @param val 被格式化的日期对象
     * @return 格式化后的日期字符串
     */
    public static String parseDateToStr(String dateFormat, Object val) {
        if (val == null) {
            return "";
        }

        // 获取日期类型对应的格式化逻辑
        Function<Object, String> formatter = FORMATTERS.get(val.getClass());

        // 如果找到对应的格式化逻辑，则调用；否则调用 toString()
        return formatter != null ? formatter.apply(val) : val.toString();
    }

    /**
     * 注册新的日期类型格式化逻辑
     *
     * @param type 日期类型
     * @param formatter 格式化逻辑
     */
    public static void registerFormatter(Class<?> type, Function<Object, String> formatter) {
        FORMATTERS.put(type, formatter);
    }
    // ====================== 兼容旧版 API ======================

    /**
     * 获取当前日期字符串（默认格式：yyyy-MM-dd）
     */
    public static String getCurrentDateStr() {
        return format(new Date(), FORMAT_YYYY_MM_DD);
    }

    /**
     * 格式化日期为字符串（默认格式：yyyy-MM-dd HH:mm:ss）
     */
    public static String format(Date date) {
        return format(date, FORMAT_YYYY_MM_DD_HH_MM_SS);
    }

    /**
     * 按指定格式格式化日期
     */
    public static String format(Date date, String pattern) {
        return DateFormatUtils.format(date, pattern);
    }

    /**
     * 解析日期字符串（自动匹配多种格式）
     */
    public static Date parseDate(String str) {
        try {
            return parseDate(str, new String[] {
                    FORMAT_YYYY_MM_DD,
                    FORMAT_YYYY_MM_DD_HH_MM_SS,
                    "yyyy/MM/dd",
                    "yyyy.MM.dd"
            });
        } catch (ParseException e) {
            throw new IllegalArgumentException("日期格式不支持: " + str, e);
        }
    }

}